Skip to content

Listen hook usersim-based tests#5269

Open
mikeagun wants to merge 4 commits into
microsoft:mainfrom
mikeagun:4480-listen-tests
Open

Listen hook usersim-based tests#5269
mikeagun wants to merge 4 commits into
microsoft:mainfrom
mikeagun:4480-listen-tests

Conversation

@mikeagun

@mikeagun mikeagun commented May 15, 2026

Copy link
Copy Markdown
Contributor

Description

Add usersim-based tests for listen hook (unit and fuzzing tests)

Depends on eBPF PRs #5267 and #5268

Also depends on usersim PR microsoft/usersim#306

Follow-up to #4480
Closes #5326

Testing

Do any existing tests cover this change? Are new tests needed?

If new tests were added:

  • Unit tests are added.
  • Driver tests are added.

Documentation

Is there any documentation impact for this change?

Installation

Is there any installer impact for this change?

@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

@mikeagun
mikeagun force-pushed the 4480-listen-tests branch from 7e51347 to b443cab Compare May 15, 2026 21:06
@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

@mikeagun
mikeagun force-pushed the 4480-listen-tests branch from b443cab to a6a9615 Compare May 15, 2026 23:10
@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

@mikeagun
mikeagun force-pushed the 4480-listen-tests branch from f90ec45 to b1e571c Compare May 18, 2026 19:52
@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

2 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request isn't linked to any GitHub issue. Please reference an issue with a keyword such as Fixes #123, Closes #456, etc., so the work can be tracked.

@mikeagun
mikeagun force-pushed the 4480-listen-tests branch 5 times, most recently from 019e3af to dfc977d Compare May 27, 2026 16:47
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request May 28, 2026
Updates the netsh `show sections` golden output and the libbpf JIT
test map-iteration assertions to include the new `listen_connection_policy_map`
and the cgroup/listen4 + cgroup/listen6 attach types.

These test updates were previously held back on the listen-tests PR (microsoft#5269),
but the production code that emits the new netsh sections and the new map
ships on this PR. Without these matching test changes, the CI runs on this
PR fail at:

  tests/end_to_end/netsh_test.cpp(440): REQUIRE(output_matches)
  tests/unit/libbpf_test_jit.cpp(462): REQUIRE(map == nullptr)
  tests/unit/libbpf_test_jit.cpp(544): REQUIRE(map == nullptr)

Moving the matching test deltas with the impl keeps CI green here. The
remaining in-process tests, fuzzer additions, and usersim bump stay on
microsoft#5269.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mikeagun
mikeagun force-pushed the 4480-listen-tests branch 2 times, most recently from 54c4f00 to 7dadada Compare May 29, 2026 16:01
@mikeagun mikeagun changed the title Listen hook tests Listen hook usersim-based tests May 29, 2026
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request Jun 8, 2026
Updates the netsh `show sections` golden output and the libbpf JIT
test map-iteration assertions to include the new `listen_connection_policy_map`
and the cgroup/listen4 + cgroup/listen6 attach types.

These test updates were previously held back on the listen-tests PR (microsoft#5269),
but the production code that emits the new netsh sections and the new map
ships on this PR. Without these matching test changes, the CI runs on this
PR fail at:

  tests/end_to_end/netsh_test.cpp(440): REQUIRE(output_matches)
  tests/unit/libbpf_test_jit.cpp(462): REQUIRE(map == nullptr)
  tests/unit/libbpf_test_jit.cpp(544): REQUIRE(map == nullptr)

Moving the matching test deltas with the impl keeps CI green here. The
remaining in-process tests, fuzzer additions, and usersim bump stay on
microsoft#5269.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mikeagun
mikeagun force-pushed the 4480-listen-tests branch from 7dadada to 5f42c54 Compare June 8, 2026 18:47
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request Jun 8, 2026
Updates the netsh `show sections` golden output and the libbpf JIT
test map-iteration assertions to include the new `listen_connection_policy_map`
and the cgroup/listen4 + cgroup/listen6 attach types.

These test updates were previously held back on the listen-tests PR (microsoft#5269),
but the production code that emits the new netsh sections and the new map
ships on this PR. Without these matching test changes, the CI runs on this
PR fail at:

  tests/end_to_end/netsh_test.cpp(440): REQUIRE(output_matches)
  tests/unit/libbpf_test_jit.cpp(462): REQUIRE(map == nullptr)
  tests/unit/libbpf_test_jit.cpp(544): REQUIRE(map == nullptr)

Moving the matching test deltas with the impl keeps CI green here. The
remaining in-process tests, fuzzer additions, and usersim bump stay on
microsoft#5269.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mikeagun
mikeagun force-pushed the 4480-listen-tests branch 3 times, most recently from 70046dd to 14791f3 Compare June 10, 2026 00:53
@mikeagun
mikeagun marked this pull request as ready for review June 10, 2026 16:15
Alan-Jowett pushed a commit to Alan-Jowett/ebpf-for-windows that referenced this pull request Jun 10, 2026
* Add listen hook to sock_addr: WFP callout, classify, types, and registration

Add support for eBPF programs that hook into listen() socket calls via
WFP ALE_AUTH_LISTEN_V4/V6 layers, enabling security/observability for
listen operations. Closes microsoft#4480.

- Define EBPF_ATTACH_TYPE_CGROUP_INET4/6_LISTEN GUIDs and
  BPF_CGROUP_INET4/6_LISTEN enum values.
- Add EBPF_HOOK_ALE_AUTH_LISTEN_V4/V6 hook IDs.
- Register WFP callouts for ALE_AUTH_LISTEN_V4/V6 layers.
- Implement net_ebpf_extension_sock_addr_authorize_listen_classify() with
  permit/block/hard-permit verdict handling.
- Add _net_ebpf_extension_sock_addr_copy_wfp_listen_fields() for
  extracting listen-specific WFP fields (local address/port only).
- Add cgroup/listen4 and cgroup/listen6 section definitions.
- Wire up _does_attach_type_support_attachable_fd() for listen types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Expose interface_type/tunnel_type WFP fields for listen hooks

Add FWPS_FIELD_ALE_AUTH_LISTEN_V4/V6_INTERFACE_TYPE and _TUNNEL_TYPE
to the wfp_connection_fields[] table and populate them in
_net_ebpf_extension_sock_addr_copy_wfp_listen_fields().

Extend the bpf_sock_addr_get_network_context helper to accept listen
hook IDs so BPF programs at the listen attach point can retrieve
interface_type and tunnel_type via the versioned helper struct.

Update documentation comments on bpf_sock_addr_network_context_t and
the get_network_context helper to list LISTEN as a supported attach type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add verbose log for missing USER_ID in listen hook

Add a VERBOSE-level trace log when the USER_ID field is not present
in the listen classify callback, matching the existing pattern for
PROCESS_ID. Addresses review feedback from FetoiuCatalin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document why next_hop_interface_luid/sub_interface_index are unspecified at listen

Expand the inline comment on the NET_IF*_UNSPECIFIED assignments in
_net_ebpf_extension_sock_addr_copy_wfp_listen_fields to explain that the
ALE_AUTH_LISTEN WFP layer has no next-hop concept and does not expose a
SUB_INTERFACE_INDEX field (unlike ALE_AUTH_CONNECT/RECV_ACCEPT), and to
point readers at sock_addr_ctx->base.interface_luid (populated from
FWPS_FIELD_ALE_AUTH_LISTEN_V*_IP_LOCAL_INTERFACE) for the local interface
LUID, which is exposed to BPF programs via bpf_sock_addr_t::interface_luid.

Addresses review feedback from FetoiuCatalin and keith-horton on PR microsoft#5268.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add driver-level socket tests for listen hook

Move driver-level integration tests for the new listen hook from the
follow-up test PR into the implementation PR so the implementation
ships with end-to-end test coverage. In-process tests
(netebpfext_unit, netebpfext_fuzzer) and the supporting usersim
submodule bump remain on the follow-up PR.

- Add `authorize_listen4` / `authorize_listen6` programs.
- Add `listen_connection_policy_map` for policy-based listen filtering.

- Add a listen network-context helper sample.

- Regenerate the bpf2c golden outputs (`_dll.c`, `_raw.c`, `_sys.c`
  for both `cgroup_sock_addr` and `cgroup_sock_addr_helpers`) to
  match the updated samples. Generated with clang 18.1.8 to match
  the CI configuration.

Three driver-level test cases via the `execute_connection_test`
framework (test infra is already on main from microsoft#5267):

- `listen_hook_enforcement_framework` — exercises the native
  `ebpf_program_attach` path with INADDR_ANY bind (zero `local_ip`
  branch of `_copy_wfp_listen_fields`).
- `listen_enforcement_libbpf` — exercises the libbpf-compat
  `bpf_prog_attach` path with LOOPBACK bind (non-zero `local_ip`
  branch of `_copy_wfp_listen_fields`).
- `listen_hard_permit_verdict` — verifies the hard-permit verdict
  short-circuits subsequent layer evaluation.

Each test covers IPv4 and IPv6, block and allow verdicts, and asserts
the exact `WSAEACCES` error code on block.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Move user-mode test updates for listen sections to listen impl PR

Updates the netsh `show sections` golden output and the libbpf JIT
test map-iteration assertions to include the new `listen_connection_policy_map`
and the cgroup/listen4 + cgroup/listen6 attach types.

These test updates were previously held back on the listen-tests PR (microsoft#5269),
but the production code that emits the new netsh sections and the new map
ships on this PR. Without these matching test changes, the CI runs on this
PR fail at:

  tests/end_to_end/netsh_test.cpp(440): REQUIRE(output_matches)
  tests/unit/libbpf_test_jit.cpp(462): REQUIRE(map == nullptr)
  tests/unit/libbpf_test_jit.cpp(544): REQUIRE(map == nullptr)

Moving the matching test deltas with the impl keeps CI green here. The
remaining in-process tests, fuzzer additions, and usersim bump stay on
microsoft#5269.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Defensively null-check IP_LOCAL_INTERFACE in listen field copy

Mirror the bind hook's null-check pattern when copying the LUID at the
ALE_AUTH_LISTEN_V4/V6 layer. If WFP does not provide the LUID (the
`value.uint64` pointer is NULL), default to 0 (NET_IFLUID_UNSPECIFIED)
instead of dereferencing the NULL pointer.

Official documentation does not state whether IP_LOCAL_INTERFACE can be
NULL at AUTH_LISTEN, so defensive consistency with the bind hook is the
safer choice.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Test all netebpfext sock_addr helpers at the listen attach point

Extends test_listen_helpers_v4/v6 in cgroup_sock_addr_helpers.c to call all
five additional sock_addr helpers and write the captured values to
bind_helper_results_map (keys 8 and 9 for v4/v6 respectively). Extends
listen_helper_functions_validation_tcp_v4/v6 in socket_tests.cpp to read
the results back and assert the listen-appropriate value for each helper:

- bpf_get_current_pid_tgid: upper 32 bits == GetCurrentProcessId()
- bpf_get_current_logon_id: non-zero
- bpf_is_current_admin: 0 or 1 (not -1)
- bpf_sock_addr_set_redirect_context: -1 (explicit rejection at listen)
- bpf_get_socket_cookie: 0 (transport_endpoint_handle zeroed at listen)

Mirrors the bind helper validation pattern introduced in PR microsoft#5272. Addresses
review feedback on PR microsoft#5268 (thread r3376380448) asking whether other
sock_addr helpers apply to listen and whether they need test coverage.

The five helpers all behave correctly at listen without any implementation
change: four work as expected (the listen classify callback populates
process_id, access_information, and the network context fields), while
set_redirect_context is explicitly rejected and socket_cookie returns 0
because the WFP transport endpoint is not allocated/exposed at the
ALE_AUTH_LISTEN layer.

Regenerates the cgroup_sock_addr_helpers bpf2c expected files to reflect
the new helper calls in the sample program.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Michael Agun <danielagun@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
saxena-anurag added a commit that referenced this pull request Jun 10, 2026
* Fix bpf2bpf calls: global helper index, runtime_context propagation, and map access from subprograms (#5274)

* fix

* add missing sample program

* fix

* update tests

* update expected files

* update tests

* cleanup

* fix helper update callback, add tests

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* update verifier submodule (#5335)

* Implement sock_addr bind hook (#5272)

* Align bind hook with Linux: add CGROUP_INET4/6_BIND attach types

Add new attach types BPF_CGROUP_INET4_BIND and BPF_CGROUP_INET6_BIND under
the existing BPF_PROG_TYPE_CGROUP_SOCK_ADDR program type. This provides a
Linux-aligned bind hook using bpf_sock_addr_t, enabling cross-platform eBPF
programs that use 'cgroup/bind4' / 'cgroup/bind6' SEC names.

Key changes:
- New attach type GUIDs in ebpf_program_attach_type_guids.h
- New BPF enum values in ebpf_structs.h
- ELF section name mappings 'cgroup/bind4' / 'cgroup/bind6'
- New WFP callouts at ALE_RESOURCE_ASSIGNMENT_V4/V6 (distinct GUIDs from
  legacy bind callouts so both can coexist at the same WFP layer)
- New net_ebpf_extension_sock_addr_bind_classify() with bind-specific
  bpf_sock_addr context population (user_ip/user_port = local bind address,
  msg_src_* = 0)
- Multi-attach support via ATTACH_CAPABILITY_MULTI_ATTACH_WITH_WILDCARD
  (satisfies issue #5180)
- bpf_sock_addr_get_network_context extended to support bind hook IDs

Out of scope: address modification (bind hook is allow/deny only in this
phase), post-bind, unbind/release. Legacy BPF_PROG_TYPE_BIND with bind_md_t
remains unchanged for backward compatibility.

Issue: #333

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add tests for sock_addr-aligned bind hook (issue #333)

Adds sample BPF program (cgroup_sock_addr_bind.c) and socket driver tests
for the new BPF_CGROUP_INET4/6_BIND attach types.

* Document sock_addr-aligned bind hook (#333)

New docs/BindHook.md documents BPF_CGROUP_INET4_BIND and
BPF_CGROUP_INET6_BIND attach types under BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
including their relationship to the legacy bind hook, context semantics,
helper support, and Linux compatibility.

Cross-references added to docs/ConnectAuthorizationAttachTypes.md and
docs/ListenHook.md.

Sample tests/sample/cgroup_sock_addr_bind.c (added earlier in this branch)
is registered in tests/bpf2c_tests/elf_bpf.cpp, and the corresponding
expected outputs in tests/bpf2c_tests/expected/ are checked in.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Expose interface_type/tunnel_type WFP fields for bind hooks

Add FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4/V6_INTERFACE_TYPE and
_TUNNEL_TYPE to the wfp_bind_fields[] table and populate them in
_net_ebpf_extension_sock_addr_copy_wfp_bind_fields().

The get_network_context helper was already extended to accept bind
hook IDs on this branch. Update documentation comments on
bpf_sock_addr_network_context_t, the helper, and BindHook.md to
list BIND as a supported attach type.

Add cgroup/bind4 and cgroup/bind6 programs to cgroup_sock_addr_helpers.c
that call bpf_sock_addr_get_network_context and store results in the
network_context_map. Add driver tests bind_helper_functions_validation_tcp_v4
and _v6 that bind a socket and verify the network context map contains
valid interface_type and tunnel_type values.

Regenerate bpf2c expected output for the updated helper programs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix bpf2c expected output: regenerate with clang 18.1.8 matching CI

Previous regeneration used clang 19.1.4 (NuGet) but CI installs clang
18.1.8 from llvm-project GitHub releases. The different LLVM versions
produce different bytecode and #line numbers, causing bpf2c_tests to
fail on the Verify test case.

Regenerated using clang 18.1.8 from C:\Program Files\LLVM\bin\clang.exe
with the official scripts\generate_expected_bpf2c_output.ps1 script.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add matching comments to V6 entry in wfp_bind_fields

Add descriptive comments for zeroed fields in the V6 entry of
wfp_bind_fields[] to match the V4 entry style. Addresses review
feedback from FetoiuCatalin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback for bind hook (#5272)

Documentation:
- Update 'bind() requests' and 'bind() calls' wording to 'bind operations'
  in attach type/program type doc comments across ebpf_program_attach_type_guids.h,
  ebpf_structs.h, and ebpf_nethooks.h. INET4/INET6_BIND comments now read
  'when an IPv4/IPv6 socket is bound to an address/port' (dthaler, shankarseal).

Sample code:
- Document the counter_key scheme used by cgroup_sock_addr_helpers programs
  (1=connect_v4, 2=connect_v6, 3=recv_accept_v4, 4=bind_v4, 5=bind_v6) near
  the connection_count_map declaration.
- Clarify the IPv6 connection ID hash with a comment explaining that
  ctx->user_ip6[0] and ctx->user_ip6[3] are the first and last dwords
  of the IPv6 address (dthaler).

Tests:
- Refactor bind_helper_functions_validation_tcp_v4 / _v6 into a single
  parameterized bind_helper_functions_validation_test(ADDRESS_FAMILY) helper
  with two thin TEST_CASE wrappers, matching the existing
  helper_functions_validation_test pattern (dthaler).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify that bind hook fires on explicit and implicit binds

shankarseal's PR review feedback noted that "bind() calls" is misleading
since the cgroup/bind hook fires whenever a socket gets bound to a local
address/port, including implicit binds triggered by connect()/listen()/
sendto() on an unbound socket (the ALE_RESOURCE_ASSIGNMENT WFP layer
intercepts all of them).

Update BindHook.md and ConnectAuthorizationAttachTypes.md to:
- Use "bind operations" in prose (consistent with the header doc
  comment fixes in 6716dc7).
- Explicitly call out both explicit and implicit bind in the
  "Hook Integration and Flow" section and the architecture diagram.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use dual-stack AF_INET6 socket in bind helper validation test

Per shankarseal's PR review feedback. Matches the dual-stack pattern used
by helper_functions_validation_test (connect_authorization): one AF_INET6
socket with IPV6_V6ONLY=0, one sockaddr_in6 populated via IN6ADDR_SETV4MAPPED
or IN6ADDR_SETLOOPBACK. The bind() + SAFE_REQUIRE moves outside the if/else,
which now contains only the address and connection_id hash (per-family by
necessity).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Regenerate bpf2c expected files for cgroup_sock_addr_helpers

The goldens were last regenerated in `ac9b46e69` ("Fix bpf2c expected
output: regenerate with clang 18.1.8 matching CI"), but a later commit
`a65aa6c21` ("Address PR review feedback for bind hook (#5272)") added
a struct field in `tests/sample/cgroup_sock_addr_helpers.c` near line 37,
shifting every function below it down by one line. The shifted `#line`
directives in the goldens no longer matched bpf2c's output (golden expected
`#line 53` but bpf2c emits `#line 54` for `test_sock_addr_helpers_v4`),
causing `cgroup_sock_addr_helpers _test_mode::Verify` to fail.

Regenerated via `scripts/generate_expected_bpf2c_output.ps1 .\x64\Debug\`
to bring the goldens back in sync with the current sample source. Only the
three `cgroup_sock_addr_helpers_{dll,raw,sys}.c` files changed; the other
sample goldens are byte-identical to their prior state.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR #5272 review feedback

Bind multi-attach correctness and documented-contract enforcement:
* Add bind-specific process_verdict that accumulates the most-restrictive
  verdict and short-circuits on REJECT (fixes [REJECT, PROCEED_SOFT]
  incorrectly permitting the bind under multi-attach).
* Normalize unknown sock_addr return values to REJECT in both the bind and
  shared (connect / auth_connect) verdict paths per ebpf_nethooks.h.
* NULL-safe `bpf_get_current_logon_id` / `bpf_is_current_admin` for system
  binds with no user token.

Helper test coverage at the bind attach point:
* Exercise all bind-supported helpers from the v4/v6 bind sample and assert
  per-helper return values + the existing connection_count_map updates.
* Add unknown-verdict regression tests for bind and connect_authorization.

Docs:
* BindHook.md: note address/port modification divergence from Linux; document
  socket_cookie / logon_id / is_admin behavior at the bind layer.
* ebpf_nethooks.h: mark next_hop_interface_luid / sub_interface_index as
  unspecified at BIND.

Regenerate cgroup_sock_addr_helpers bpf2c expected files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix brace-elision bug in connection_test_connect_authorization_unknown_verdict

The single-program initializer was using a two-program brace pattern, leaving
program_spec.attach_type uninitialized and the program name truncated.
Validated on the test VM: the 4 affected cases now pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* bpf_is_current_admin: return -1 when admin status cannot be determined

Per the helper's documented contract in include/bpf_helper_defs.h (<0 = error,
0 = not admin, 1 = admin), returning 0 for a missing user token incorrectly
indicates `not admin`. Return -1 (error) instead and update BindHook.md
helper table.

Addresses #5272 (comment)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Michael Agun <danielagun@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add listen hook implementation to sock_addr (#5268)

* Add listen hook to sock_addr: WFP callout, classify, types, and registration

Add support for eBPF programs that hook into listen() socket calls via
WFP ALE_AUTH_LISTEN_V4/V6 layers, enabling security/observability for
listen operations. Closes #4480.

- Define EBPF_ATTACH_TYPE_CGROUP_INET4/6_LISTEN GUIDs and
  BPF_CGROUP_INET4/6_LISTEN enum values.
- Add EBPF_HOOK_ALE_AUTH_LISTEN_V4/V6 hook IDs.
- Register WFP callouts for ALE_AUTH_LISTEN_V4/V6 layers.
- Implement net_ebpf_extension_sock_addr_authorize_listen_classify() with
  permit/block/hard-permit verdict handling.
- Add _net_ebpf_extension_sock_addr_copy_wfp_listen_fields() for
  extracting listen-specific WFP fields (local address/port only).
- Add cgroup/listen4 and cgroup/listen6 section definitions.
- Wire up _does_attach_type_support_attachable_fd() for listen types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Expose interface_type/tunnel_type WFP fields for listen hooks

Add FWPS_FIELD_ALE_AUTH_LISTEN_V4/V6_INTERFACE_TYPE and _TUNNEL_TYPE
to the wfp_connection_fields[] table and populate them in
_net_ebpf_extension_sock_addr_copy_wfp_listen_fields().

Extend the bpf_sock_addr_get_network_context helper to accept listen
hook IDs so BPF programs at the listen attach point can retrieve
interface_type and tunnel_type via the versioned helper struct.

Update documentation comments on bpf_sock_addr_network_context_t and
the get_network_context helper to list LISTEN as a supported attach type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add verbose log for missing USER_ID in listen hook

Add a VERBOSE-level trace log when the USER_ID field is not present
in the listen classify callback, matching the existing pattern for
PROCESS_ID. Addresses review feedback from FetoiuCatalin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document why next_hop_interface_luid/sub_interface_index are unspecified at listen

Expand the inline comment on the NET_IF*_UNSPECIFIED assignments in
_net_ebpf_extension_sock_addr_copy_wfp_listen_fields to explain that the
ALE_AUTH_LISTEN WFP layer has no next-hop concept and does not expose a
SUB_INTERFACE_INDEX field (unlike ALE_AUTH_CONNECT/RECV_ACCEPT), and to
point readers at sock_addr_ctx->base.interface_luid (populated from
FWPS_FIELD_ALE_AUTH_LISTEN_V*_IP_LOCAL_INTERFACE) for the local interface
LUID, which is exposed to BPF programs via bpf_sock_addr_t::interface_luid.

Addresses review feedback from FetoiuCatalin and keith-horton on PR #5268.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add driver-level socket tests for listen hook

Move driver-level integration tests for the new listen hook from the
follow-up test PR into the implementation PR so the implementation
ships with end-to-end test coverage. In-process tests
(netebpfext_unit, netebpfext_fuzzer) and the supporting usersim
submodule bump remain on the follow-up PR.

- Add `authorize_listen4` / `authorize_listen6` programs.
- Add `listen_connection_policy_map` for policy-based listen filtering.

- Add a listen network-context helper sample.

- Regenerate the bpf2c golden outputs (`_dll.c`, `_raw.c`, `_sys.c`
  for both `cgroup_sock_addr` and `cgroup_sock_addr_helpers`) to
  match the updated samples. Generated with clang 18.1.8 to match
  the CI configuration.

Three driver-level test cases via the `execute_connection_test`
framework (test infra is already on main from #5267):

- `listen_hook_enforcement_framework` — exercises the native
  `ebpf_program_attach` path with INADDR_ANY bind (zero `local_ip`
  branch of `_copy_wfp_listen_fields`).
- `listen_enforcement_libbpf` — exercises the libbpf-compat
  `bpf_prog_attach` path with LOOPBACK bind (non-zero `local_ip`
  branch of `_copy_wfp_listen_fields`).
- `listen_hard_permit_verdict` — verifies the hard-permit verdict
  short-circuits subsequent layer evaluation.

Each test covers IPv4 and IPv6, block and allow verdicts, and asserts
the exact `WSAEACCES` error code on block.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Move user-mode test updates for listen sections to listen impl PR

Updates the netsh `show sections` golden output and the libbpf JIT
test map-iteration assertions to include the new `listen_connection_policy_map`
and the cgroup/listen4 + cgroup/listen6 attach types.

These test updates were previously held back on the listen-tests PR (#5269),
but the production code that emits the new netsh sections and the new map
ships on this PR. Without these matching test changes, the CI runs on this
PR fail at:

  tests/end_to_end/netsh_test.cpp(440): REQUIRE(output_matches)
  tests/unit/libbpf_test_jit.cpp(462): REQUIRE(map == nullptr)
  tests/unit/libbpf_test_jit.cpp(544): REQUIRE(map == nullptr)

Moving the matching test deltas with the impl keeps CI green here. The
remaining in-process tests, fuzzer additions, and usersim bump stay on
#5269.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Defensively null-check IP_LOCAL_INTERFACE in listen field copy

Mirror the bind hook's null-check pattern when copying the LUID at the
ALE_AUTH_LISTEN_V4/V6 layer. If WFP does not provide the LUID (the
`value.uint64` pointer is NULL), default to 0 (NET_IFLUID_UNSPECIFIED)
instead of dereferencing the NULL pointer.

Official documentation does not state whether IP_LOCAL_INTERFACE can be
NULL at AUTH_LISTEN, so defensive consistency with the bind hook is the
safer choice.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Test all netebpfext sock_addr helpers at the listen attach point

Extends test_listen_helpers_v4/v6 in cgroup_sock_addr_helpers.c to call all
five additional sock_addr helpers and write the captured values to
bind_helper_results_map (keys 8 and 9 for v4/v6 respectively). Extends
listen_helper_functions_validation_tcp_v4/v6 in socket_tests.cpp to read
the results back and assert the listen-appropriate value for each helper:

- bpf_get_current_pid_tgid: upper 32 bits == GetCurrentProcessId()
- bpf_get_current_logon_id: non-zero
- bpf_is_current_admin: 0 or 1 (not -1)
- bpf_sock_addr_set_redirect_context: -1 (explicit rejection at listen)
- bpf_get_socket_cookie: 0 (transport_endpoint_handle zeroed at listen)

Mirrors the bind helper validation pattern introduced in PR #5272. Addresses
review feedback on PR #5268 (thread r3376380448) asking whether other
sock_addr helpers apply to listen and whether they need test coverage.

The five helpers all behave correctly at listen without any implementation
change: four work as expected (the listen classify callback populates
process_id, access_information, and the network context fields), while
set_redirect_context is explicitly rejected and socket_cookie returns 0
because the WFP transport endpoint is not allocated/exposed at the
ALE_AUTH_LISTEN layer.

Regenerates the cgroup_sock_addr_helpers bpf2c expected files to reflect
the new helper calls in the sample program.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Michael Agun <danielagun@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: D. Michael Agun <mikeagun@gmail.com>
Co-authored-by: Michael Agun <danielagun@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@dthaler dthaler left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just some questions about whether we can add const to a couple more arguments

Comment thread tests/netebpfext_unit/netebpf_ext_helper.h Outdated
Comment thread tests/sample/cgroup_sock_addr.c Outdated
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request Jun 19, 2026
…ters_t*

Update all 11 test_* helpers in netebpf_ext_helper.h to take a
const fwp_classify_parameters_t* (was non-const). Body uses const_cast
to bridge to the underlying non-const usersim_fwp_* API. This enforces
the immutability discipline at the wrapper boundary so callers cannot
accidentally rely on per-call mutation of the shared parameters object
(e.g., the sock_addr_listen_invoke test reuses one parameters object
across multiple v4/v6 calls).

Scope: all helpers in this file for in-file consistency. Touched helpers
(unchanged behavior, signature only):
  test_bind_ipv4
  test_cgroup_inet4_recv_accept / test_cgroup_inet6_recv_accept
  test_cgroup_inet4_connect / test_cgroup_inet6_connect
  test_cgroup_inet4_connect_authorization / test_cgroup_inet6_connect_authorization
  test_sock_ops_v4 / test_sock_ops_v6 (flow_id out-param remains non-const)
  test_cgroup_inet4_listen / test_cgroup_inet6_listen

Addresses review comment from @dthaler on PR microsoft#5269 thread
PRRT_kwDOFTPWZc6Il6Da (tests/netebpfext_unit/netebpf_ext_helper.h:113).
The companion sample-side change (const ctx on authorize_listen_v4/v6)
is deferred to a follow-up pending an unrelated local verifier build
issue affecting bpf2c golden regeneration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request Jun 19, 2026
Add const qualifier to the bpf_sock_addr_t* ctx parameter on
authorize_listen_v4 and authorize_listen_v6 in tests/sample/cgroup_sock_addr.c.
Both helpers only READ from ctx (user_ip4, user_ip6, user_port, protocol),
so const tightens the contract at no runtime cost. The SEC programs
(authorize_listen4, authorize_listen6) keep their non-const top-level
ctx — they call these inline helpers with implicit non-const-to-const
conversion, which is well-formed C.

The bpf2c-emitted goldens are unchanged: clang's BPF backend produces
identical instructions and the bpf2c output does not include the
const qualifier from the source-level BTF, so no golden regen is
required.

Addresses review comment from @dthaler on PR microsoft#5269 thread
PRRT_kwDOFTPWZc6Il7uJ (tests/sample/cgroup_sock_addr.c:106):
"I think at least ctx can be const here."

Applied symmetrically to both v4 and v6 helpers (the reviewer
flagged v6 only, but the v4/v6 pair should be consistent and would
likely draw a re-comment on v4 otherwise).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request Jun 19, 2026
…ters_t*

Update all 11 test_* helpers in netebpf_ext_helper.h to take a
const fwp_classify_parameters_t* (was non-const). Body uses const_cast
to bridge to the underlying non-const usersim_fwp_* API. This enforces
the immutability discipline at the wrapper boundary so callers cannot
accidentally rely on per-call mutation of the shared parameters object
(e.g., the sock_addr_listen_invoke test reuses one parameters object
across multiple v4/v6 calls).

Scope: all helpers in this file for in-file consistency. Touched helpers
(unchanged behavior, signature only):
  test_bind_ipv4
  test_cgroup_inet4_recv_accept / test_cgroup_inet6_recv_accept
  test_cgroup_inet4_connect / test_cgroup_inet6_connect
  test_cgroup_inet4_connect_authorization / test_cgroup_inet6_connect_authorization
  test_sock_ops_v4 / test_sock_ops_v6 (flow_id out-param remains non-const)
  test_cgroup_inet4_listen / test_cgroup_inet6_listen

Addresses review comment from @dthaler on PR microsoft#5269 thread
PRRT_kwDOFTPWZc6Il6Da (tests/netebpfext_unit/netebpf_ext_helper.h:113).
The companion sample-side change (const ctx on authorize_listen_v4/v6)
is deferred to a follow-up pending an unrelated local verifier build
issue affecting bpf2c golden regeneration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mikeagun pushed a commit to mikeagun/ebpf-for-windows that referenced this pull request Jun 19, 2026
Add const qualifier to the bpf_sock_addr_t* ctx parameter on
authorize_listen_v4 and authorize_listen_v6 in tests/sample/cgroup_sock_addr.c.
Both helpers only READ from ctx (user_ip4, user_ip6, user_port, protocol),
so const tightens the contract at no runtime cost. The SEC programs
(authorize_listen4, authorize_listen6) keep their non-const top-level
ctx — they call these inline helpers with implicit non-const-to-const
conversion, which is well-formed C.

The bpf2c-emitted goldens are unchanged: clang's BPF backend produces
identical instructions and the bpf2c output does not include the
const qualifier from the source-level BTF, so no golden regen is
required.

Addresses review comment from @dthaler on PR microsoft#5269 thread
PRRT_kwDOFTPWZc6Il7uJ (tests/sample/cgroup_sock_addr.c:106):
"I think at least ctx can be const here."

Applied symmetrically to both v4 and v6 helpers (the reviewer
flagged v6 only, but the v4/v6 pair should be consistent and would
likely draw a re-comment on v4 otherwise).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mikeagun
mikeagun force-pushed the 4480-listen-tests branch from d6f5ce7 to 3c2bdf7 Compare June 19, 2026 16:25
dthaler
dthaler previously approved these changes Jun 20, 2026
Comment thread tests/libfuzzer/netebpfext_fuzzer/libfuzz_harness.cpp
Comment thread tests/libfuzzer/netebpfext_fuzzer/libfuzz_harness.cpp
Michael Agun and others added 3 commits July 13, 2026 15:23
In-process tests that exercise the listen hook implementation via
netebpfext's usermode shim, plus libfuzzer harness coverage. The
driver-level integration tests (tests/socket/socket_tests.cpp) and the
matching user-mode test deltas (tests/end_to_end/netsh_test.cpp,
tests/unit/libbpf_test_jit.cpp) ship on the implementation PR (microsoft#5268);
this PR holds the tests that depend on the bumped usersim helpers and
on test-host setup not present on the implementation PR.

## usersim submodule
- Bump `external/usersim` f1739f5 -> acb95c9 to add the
  `usersim_fwp_cgroup_inet4_listen` / `usersim_fwp_cgroup_inet6_listen`
  helpers and the renamed `cgroup_inet_listen` API used below.

## In-process unit tests (tests/netebpfext_unit/)
- `netebpf_ext_helper.h`: add `test_cgroup_inet4_listen` and
  `test_cgroup_inet6_listen` helpers that drive the WFP classify
  callout via the usermode shim.
- `netebpfext_unit.cpp`: add `sock_addr_listen_invoke` (verifies
  permit / block / hard-permit verdicts for IPv4 and IPv6) and
  `sock_addr_listen_context` (verifies `bpf_sock_addr` context
  fields populated from the ALE_AUTH_LISTEN WFP layer).

## Libfuzzer harness (tests/libfuzzer/netebpfext_fuzzer/)
- `libfuzz_harness.cpp`: add `test_cgroup_inet4_listen` and
  `test_cgroup_inet6_listen` invocations to the
  BPF_PROG_TYPE_CGROUP_SOCK_ADDR arm to fuzz the new classify and
  field-copy code paths. Also wire the existing fuzzer-controlled
  return_value byte through program_result for all hooks.
- `corpus/{bind,cgroup_sock_addr,sock_ops,xdp}`: extend each corpus
  entry from 12 bytes to 16 bytes to carry the program_result byte.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ters_t*

Update all 11 test_* helpers in netebpf_ext_helper.h to take a
const fwp_classify_parameters_t* (was non-const). Body uses const_cast
to bridge to the underlying non-const usersim_fwp_* API. This enforces
the immutability discipline at the wrapper boundary so callers cannot
accidentally rely on per-call mutation of the shared parameters object
(e.g., the sock_addr_listen_invoke test reuses one parameters object
across multiple v4/v6 calls).

Scope: all helpers in this file for in-file consistency. Touched helpers
(unchanged behavior, signature only):
  test_bind_ipv4
  test_cgroup_inet4_recv_accept / test_cgroup_inet6_recv_accept
  test_cgroup_inet4_connect / test_cgroup_inet6_connect
  test_cgroup_inet4_connect_authorization / test_cgroup_inet6_connect_authorization
  test_sock_ops_v4 / test_sock_ops_v6 (flow_id out-param remains non-const)
  test_cgroup_inet4_listen / test_cgroup_inet6_listen

Addresses review comment from @dthaler on PR microsoft#5269 thread
PRRT_kwDOFTPWZc6Il6Da (tests/netebpfext_unit/netebpf_ext_helper.h:113).
The companion sample-side change (const ctx on authorize_listen_v4/v6)
is deferred to a follow-up pending an unrelated local verifier build
issue affecting bpf2c golden regeneration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add const qualifier to the bpf_sock_addr_t* ctx parameter on
authorize_listen_v4 and authorize_listen_v6 in tests/sample/cgroup_sock_addr.c.
Both helpers only READ from ctx (user_ip4, user_ip6, user_port, protocol),
so const tightens the contract at no runtime cost. The SEC programs
(authorize_listen4, authorize_listen6) keep their non-const top-level
ctx — they call these inline helpers with implicit non-const-to-const
conversion, which is well-formed C.

The bpf2c-emitted goldens are unchanged: clang's BPF backend produces
identical instructions and the bpf2c output does not include the
const qualifier from the source-level BTF, so no golden regen is
required.

Addresses review comment from @dthaler on PR microsoft#5269 thread
PRRT_kwDOFTPWZc6Il7uJ (tests/sample/cgroup_sock_addr.c:106):
"I think at least ctx can be const here."

Applied symmetrically to both v4 and v6 helpers (the reviewer
flagged v6 only, but the v4/v6 pair should be consistent and would
likely draw a re-comment on v4 otherwise).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The fuzzer's CGROUP_SOCK_ADDR desired_attach_types allowlist omitted
BPF_CGROUP_INET4_LISTEN / BPF_CGROUP_INET6_LISTEN, so the hook client
refused the LISTEN providers and test_cgroup_inet4/6_listen() never
exercised the program. Add the two LISTEN attach types so the listen
fuzz path actually reaches the program under test.

Resolves review feedback from @shankarseal and @Alan-Jowett on microsoft#5269.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c2ba0624-5e1d-4385-9972-eec1b8c595f1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Add usersim-based tests for listen hook

5 participants